﻿using MelonLoader;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEngine;

/// <summary>
/// 当你手动修改了此命名空间，需要去模组编辑器修改对应的新命名空间，程序集也需要修改命名空间，否则DLL将加载失败！！！
/// </summary>
namespace MOD_OlBGDZ
{
    /// <summary>
    /// 此类是模组的主类
    /// </summary>
    public class ModMain
    {
        private TimerCoroutine corUpdate;
        private static HarmonyLib.Harmony harmony;
        internal static Properties.Settings Settings => Properties.Settings.Default;

        public Il2CppSystem.Action<ETypeData> Il2CppOnIntoWorld;
        public Il2CppSystem.Action<ETypeData> Il2CppOnBattleStart;

        /// <summary>
        /// MOD初始化，进入游戏时会调用此函数
        /// </summary>
        public void Init()
        {
            //使用了Harmony补丁功能的，需要手动启用补丁。
            //启动当前程序集的所有补丁
            if (harmony != null)
            {
                harmony.UnpatchSelf();
                harmony = null;
            }
            if (harmony == null)
            {
                harmony = new HarmonyLib.Harmony("MOD_OlBGDZ");
            }
            harmony.PatchAll(Assembly.GetExecutingAssembly());

            corUpdate = g.timer.Frame(new Action(OnUpdate), 1, true);

            Il2CppOnIntoWorld = (Il2CppSystem.Action<ETypeData>)OnIntoWorld;
            g.events.On(EGameType.IntoWorld, Il2CppOnIntoWorld);
            MelonLogger.Msg($"[{Settings.ModName}] Event Manager listened on: {nameof(EGameType.IntoWorld)}");

            Il2CppOnBattleStart = (Il2CppSystem.Action<ETypeData>)OnBattleStart;
            g.events.On(EBattleType.BattleStart, Il2CppOnBattleStart);
            MelonLogger.Msg($"[{Settings.ModName}] Event Manager listened on: {nameof(EBattleType.BattleStart)}");

        }

        public void OnIntoWorld(ETypeData eventData)
        {
            MelonLogger.Msg(ConsoleColor.Blue, $"[{Settings.ModName}] Event Manager broadcast: {nameof(EGameType.IntoWorld)}");
            MelonLogger.Msg($"[{Settings.ModName}] Start modifying");
            ModifyTaskReawrd();
            ModifySchoolTaskReward();
            ModifyWorldBlockCost();
            ModifyPropsDrop();
            ModifyFortuitousBuildingHerbalGardenDramaReward();
            ModifyRoleDiscoveryExperienceGain();
            ModifyRoleBattleExchangeTaoFirmnessGain();
            ModifyRoleCultivateTogetherFriendlinessGain();
            ModifyBattleSkillGrowExperience();
            ModifyBattleSkillPrefixTracebackPoint();
            ModifyBattleSkillLearn();
            MelonLogger.Msg($"[{Settings.ModName}] Modification completed");
        }

        public void OnBattleStart(ETypeData eventData)
        {
            MelonLogger.Msg(ConsoleColor.Blue, $"[{Settings.ModName}] Event Manager broadcast: {nameof(EBattleType.BattleStart)}");
            MelonLogger.Msg($"[{Settings.ModName}] Start modifying");
            ModifyPropsPickDistance();
            MelonLogger.Msg($"[{Settings.ModName}] Modification completed");
        }

        /// <summary>
        /// MOD销毁，回到主界面，会调用此函数并重新初始化MOD
        /// </summary>
        public void Destroy()
        {
            g.timer.Stop(corUpdate);

            g.events.Off(EGameType.IntoWorld, Il2CppOnIntoWorld);
            MelonLogger.Msg(ConsoleColor.Blue, $"[{Settings.ModName}] Event Manager listened off: {nameof(EGameType.IntoWorld)}");

            g.events.Off(EBattleType.BattleStart, Il2CppOnBattleStart);
            MelonLogger.Msg(ConsoleColor.Blue, $"[{Settings.ModName}] Event Manager listened off: {nameof(EBattleType.BattleStart)}");

            if (harmony != null)
            {
                harmony.UnpatchSelf();
                harmony = null;
            }
        }

        /// <summary>
        /// 每帧调用的函数
        /// </summary>
        private void OnUpdate()
        {

        }

        /// <summary>
        /// 任务奖励×2.5: 灵石, 城主令, 声望, 战功
        /// </summary>
        private void ModifyTaskReawrd()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify task reward");

            new Il2CppSystem.Collections.Generic.List<ConfTaskBaseItem>(
                g.conf.taskBase.allConfList.Pointer).ForEach(
                (Action<ConfTaskBaseItem>)((item) =>
            {
                if (item.rewardMoney > 0) { item.rewardMoney = (int)Math.Ceiling(item.rewardMoney * 2.5); }
                if (item.rewardToken > 0) { item.rewardToken = (int)Math.Ceiling(item.rewardToken * 2.5); }
                if (item.rewardReputation > 0) { item.rewardReputation = (int)Math.Ceiling(item.rewardReputation * 2.5); }
                if (item.contribution > 0) { item.contribution = (int)Math.Ceiling(item.contribution * 2.5); }
            }));
        }

        /// <summary>
        /// 宗门任务奖励×2.5: 灵石, 宗门贡献, 声望, 宗门提升
        /// </summary>
        private void ModifySchoolTaskReward()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify school task reward");

            new Il2CppSystem.Collections.Generic.List<ConfSchoolTaskTypeBaseItem>(
                g.conf.schoolTaskTypeBase.allConfList.Pointer).ForEach(
                (Action<ConfSchoolTaskTypeBaseItem>)((item) =>
            {
                if (item.money > 0) { item.money = (int)Math.Ceiling(item.money * 2.5); }
                if (item.rewardContribution > 0) { item.rewardContribution = (int)Math.Ceiling(item.rewardContribution * 2.5); }
                if (item.reputation > 0) { item.reputation = (int)Math.Ceiling(item.reputation * 2.5); }

                var il2CppSchoolAttr = item.schollAttr;
                for (int i = 0; i < il2CppSchoolAttr.Length; i++)
                {
                    var schollResourceParsedValue = double.Parse(il2CppSchoolAttr[i][1], CultureInfo.InvariantCulture);
                    if (schollResourceParsedValue > 0.0)
                    {
                        int schoolResourceValueChanged = (int)Math.Ceiling(schollResourceParsedValue * 2.5);
                        il2CppSchoolAttr[i][1] = ToolBox.ToRawString(schoolResourceValueChanged);
                    }
                }
            }));
        }

        private void ModifyWorldBlockCost()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify world block cost");

            // 大地图修炼时间消耗÷2.5
            new Il2CppSystem.Collections.Generic.List<ConfWorldBlockGetExpItem>(
                g.conf.worldBlockGetExp.allConfList.Pointer).ForEach(
                (Action<ConfWorldBlockGetExpItem>)((item) =>
            {
                if (item.costDay > 0) { item.costDay = (int)Math.Ceiling(item.costDay / 2.5); }
            }));

            // 大地图采药时间消耗÷2.5
            new Il2CppSystem.Collections.Generic.List<ConfWorldBlockHerbItem>(
                g.conf.worldBlockHerb.allConfList.Pointer).ForEach(
                (Action<ConfWorldBlockHerbItem>)((item) =>
            {
                if (item.costDay > 0) { item.costDay = (int)Math.Ceiling(item.costDay / 2.5); }
            }));

            // 大地图采矿时间消耗÷2.5
            new Il2CppSystem.Collections.Generic.List<ConfWorldBlockMineItem>(
                g.conf.worldBlockMine.allConfList.Pointer).ForEach(
                (Action<ConfWorldBlockMineItem>)((item) =>
            {
                if (item.costDay > 0) { item.costDay = (int)Math.Ceiling(item.costDay / 2.5); }
            }));

            // 大地图采矿(鉴识类)时间消耗÷2.5
            new Il2CppSystem.Collections.Generic.List<ConfWorldBlockMineBookItem>(
                g.conf.worldBlockMineBook.allConfList.Pointer).ForEach(
                (Action<ConfWorldBlockMineBookItem>)((item) =>
            {
                if (item.costDay > 0) { item.costDay = (int)Math.Ceiling(item.costDay / 2.5); }
            }));

            // 大地图操作(采集药材\探索金石\风水勘测\灵气修炼)时间消耗÷2.5
            new Il2CppSystem.Collections.Generic.List<ConfWorldBlockOperationItem>(
                g.conf.worldBlockOperation.allConfList.Pointer).ForEach(
                (Action<ConfWorldBlockOperationItem>)((item) =>
            {
                if (item.cost > 0) { item.cost = (int)Math.Ceiling(item.cost / 2.5); }
            }));
        }

        /// <summary>
        /// 物品掉落×2.5
        /// </summary>
        private void ModifyPropsDrop()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify props drop");

            HashSet<int> byPropsId = new HashSet<int>()
            {
                10001, // 灵石
                10011, // 宗门贡献

                5071015, 5071025, 5071035, 5071045, 5071055, 5071065, // 筑基(lv2)突破材料: 灵气碎片
                5071075, 5071085, 5071095, 5071105, 5071115, 5071125, // 金丹(lv4)突破材料: 灵珠碎片
                5071255, 5071265, // 元婴(lv6)突破材料: 天道之气碎片, 地道之气碎片
                5071135, 5071145, 5071155, 5071165, 5071175, 5071185, // 悟道(lv8)突破材料: 灵斗气碎片
                5071195, 5071205, 5071215, 5071225, 5071235, 5071245, // 登仙(lv10)突破材料: 灵斗珠碎片
                5021413, 5021414, 5021415, // 炼气~筑基(lv1~2)功法修炼材料: 魂石
                5021423, 5021424, 5021425, // 结晶~金丹(lv3~4)功法修炼材料: 魂晶
                5021433, 5021434, 5021435, // 具灵~元婴(lv5~6)功法修炼材料: 魂玉
                5021443, 5021444, 5021445, // 化神~悟道(lv7~8)功法修炼材料: 精魄之息
                5021453, 5021454, 5021455, // 羽化~登仙(lv9~10)功法修炼材料: 圣灵之息
                5021462, 5021463, 5021464, 5021465, 5021466, 5021472, 5021473, 5021474, 5021475, 5021476, // 炼气~登仙(lv1~10)功法参悟材料: 悟心砂, 炼神璃
                5021734, 5021744, 5021754, 5021764, // 化神~登仙(lv7~10)神魂修炼材料: 炼魂玉
            };

            HashSet<int> byGroupId = new HashSet<int>()
            {
                3104511, // 碧云洞天药材: 极寒鱼尾草, 荨苎麻, 千叶露, 山参
            };

            new Il2CppSystem.Collections.Generic.List<ConfGameItemRewardItem>(
                g.conf.gameItemReward.allConfList.Pointer).ForEach(
                (Action<ConfGameItemRewardItem>)((item) =>
            {
                if (byPropsId.Contains(item.item))
                {
                    item.numMin *= 2.5f;
                    item.numMax *= 2.5f;
                }
                else if(byGroupId.Contains(item.rewardID))
                {
                    item.numMin *= 2.5f;
                    item.numMax *= 2.5f;
                }
            }));
        }

        /// <summary>
        /// 奇遇建筑药园奖励×6.25(＝2.5×2.5)
        /// </summary>
        private void ModifyFortuitousBuildingHerbalGardenDramaReward()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify fortuitous building herbal garden drama reward");

            HashSet<int> dramaOptions = new HashSet<int>()
            {
                6107211, 6107212, 6107213, 6107214, 6107215, // 对应剧情对话: 你在周围采集了一番，获得了一些药材。
                6107221, 6107222, 6107223, 6107224, 6107225, // 对应剧情对话: 你在周围采集了一番，获得了大量的药材。
                6107241, 6107242, 6107243, 6107244, 6107245, // 对应剧情对话: 你战胜了妖兽，在药园中采集了一番，获得了大量的药材。
            };

            new Il2CppSystem.Collections.Generic.List<ConfDramaOptionsItem>(
              g.conf.dramaOptions.allConfList.Pointer).ForEach(
              (Action<ConfDramaOptionsItem>)((item) =>
            {
                if (dramaOptions.Contains(item.id))
                {
                    string previousDramaFunctionStringRepresentation = item.function;
                    string[] dramaFunctionList = item.function.Split('|');
                    for (int i = 0; i < dramaFunctionList.Length; i++)
                    {
                        string dramaFunction = dramaFunctionList[i];
                        (string, ITuple) dramaFunctionParsed = default;
                        switch (dramaFunction.Split('_').First())
                        {
                            case "rewardCount":
                                if (ToolBox.TryParseDramaFunction(dramaFunction, out (string, ValueTuple<int, int> Arguments) dramaFunction_rewardCount))
                                {
                                    dramaFunction_rewardCount.Arguments.Item2 = (int)Math.Ceiling(dramaFunction_rewardCount.Arguments.Item2 * 2.5 * 2.5);
                                    dramaFunctionParsed = dramaFunction_rewardCount;
                                }
                                break;
                            default:
                                break;
                        }
                        if (dramaFunctionParsed != default)
                        {
                            dramaFunctionList[i] = ToolBox.StringizeDramaFunction(dramaFunctionParsed);
                        }
                    }
                    item.function = string.Join("|", dramaFunctionList);
                }

            }));
        }

        /// <summary>
        /// 切磋\双修\论道的心得提升×2.5
        /// </summary>
        private void ModifyRoleDiscoveryExperienceGain()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify role discovery experience gain");

            g.conf.roleDrill.GetItem(13).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(13).value * 2.5); // 玩家切磋胜利时获得的心得倍数百分比最小值
            g.conf.roleDrill.GetItem(14).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(14).value * 2.5); // 玩家切磋胜利时获得的心得倍数百分比最大值
            g.conf.roleDrill.GetItem(15).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(15).value * 2.5); // 玩家切磋失败时获得的心得倍数百分比最小值
            g.conf.roleDrill.GetItem(16).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(16).value * 2.5); // 玩家切磋失败时获得的心得倍数百分比最大值

            g.conf.roleTrains.GetItem(8).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(8).value * 2.5); // 玩家双修获得的心得倍数百分比最小值
            g.conf.roleTrains.GetItem(9).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(9).value * 2.5); // 玩家双修获得的心得倍数百分比最大值

            g.conf.roleDiscovery.GetItem(45).value = ToolBox.ToRawString(
                (int)Math.Ceiling(double.Parse(g.conf.roleDiscovery.GetItem(45).value, CultureInfo.InvariantCulture) * 2.5)); // 正确选项增加的心得百分比
            g.conf.roleDiscovery.GetItem(46).value = ToolBox.ToRawString(
                (int)Math.Ceiling(double.Parse(g.conf.roleDiscovery.GetItem(46).value, CultureInfo.InvariantCulture) * 2.5)); // 错误选项增加的心得百分比
            g.conf.roleDiscovery.GetItem(47).value = ToolBox.ToRawString(
                (int)Math.Ceiling(double.Parse(g.conf.roleDiscovery.GetItem(47).value, CultureInfo.InvariantCulture) * 2.5)); // 中立选项增加的心得百分比
            g.conf.roleDiscovery.GetItem(48).value = ToolBox.ToRawString(
                (int)Math.Ceiling(double.Parse(g.conf.roleDiscovery.GetItem(48).value, CultureInfo.InvariantCulture) * 2.5)); // 上限倍数
        }

        private void ModifyRoleBattleExchangeTaoFirmnessGain()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify role battle exchange tao firmness gain");

            // 切磋的道心坚定度提升×2.5
            g.conf.roleDrill.GetItem(17).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(17).value * 2.5); // 增加的道心坚定度最小值
            g.conf.roleDrill.GetItem(18).value = (int)Math.Ceiling(g.conf.roleDrill.GetItem(18).value * 2.5); // 增加的道心坚定度最大值
        }

        private void ModifyRoleCultivateTogetherFriendlinessGain()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify role cultivate together friendliness gain");

            // 双修的亲密度提升×2.5
            g.conf.roleTrains.GetItem(2).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(2).value * 2.5); // 亲密度提升的随机最小值
            g.conf.roleTrains.GetItem(3).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(3).value * 2.5); // 亲密度提升的随机最大值

            // 双修需要消耗的天数÷2.5
            g.conf.roleTrains.GetItem(4).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(4).value / 2.5);

            // 双修冷却时间(月)÷2.5
            g.conf.roleTrains.GetItem(5).value = (int)Math.Ceiling(g.conf.roleTrains.GetItem(5).value / 2.5);
        }

        /// <summary>
        /// 功法施放获得的经验×2.5
        /// </summary>
        private void ModifyBattleSkillGrowExperience()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify battle skill grow experience");

            foreach (var id in new List<int>()
            {
                5277,
                5278,
                5279,
                5280,
                5281,
                5282,
                5283
            })
            {
                var item = g.conf.battleSkillValue.GetItem(id);
                item.value1 = ToolBox.ToRawString(double.Parse(item.value1, CultureInfo.InvariantCulture) * 2.5);
                item.value2 = ToolBox.ToRawString(double.Parse(item.value2, CultureInfo.InvariantCulture) * 2.5);
                item.value3 = ToolBox.ToRawString(double.Parse(item.value3, CultureInfo.InvariantCulture) * 2.5);
                item.value4 = ToolBox.ToRawString(double.Parse(item.value4, CultureInfo.InvariantCulture) * 2.5);
                item.value5 = ToolBox.ToRawString(double.Parse(item.value5, CultureInfo.InvariantCulture) * 2.5);
                item.value6 = ToolBox.ToRawString(double.Parse(item.value6, CultureInfo.InvariantCulture) * 2.5);
                item.value7 = ToolBox.ToRawString(double.Parse(item.value7, CultureInfo.InvariantCulture) * 2.5);
                item.value8 = ToolBox.ToRawString(double.Parse(item.value8, CultureInfo.InvariantCulture) * 2.5);
                item.value9 = ToolBox.ToRawString(double.Parse(item.value9, CultureInfo.InvariantCulture) * 2.5);
                item.value10 = ToolBox.ToRawString(double.Parse(item.value10, CultureInfo.InvariantCulture) * 2.5);
            }
        }

        /// <summary>
        /// 功法参悟的回溯点消耗减少2.5×技能境界
        /// </summary>
        private void ModifyBattleSkillPrefixTracebackPoint()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify battle skill prefix traceback point");

            new Il2CppSystem.Collections.Generic.List<ConfBattleSkillFlashCostItem>(
              g.conf.battleSkillFlashCost.allConfList.Pointer).ForEach(
              (Action<ConfBattleSkillFlashCostItem>)((item) =>
            {
                if (item.flashCost > 0)
                {
                    int reduceMeditateRecallPoint = (int)Math.Ceiling(item.grade * 2.5);
                    item.flashCost = Math.Max(1, item.flashCost - reduceMeditateRecallPoint);
                }
            }));
        }

        /// <summary>
        /// 学习秘籍
        /// </summary>
        private void ModifyBattleSkillLearn()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify battle skill learn");

            new Il2CppSystem.Collections.Generic.List<ConfBattleSkillLearnItem>(
                g.conf.battleSkillLearn.allConfList.Pointer).ForEach(
                (Action<ConfBattleSkillLearnItem>)((item) =>
            {
                switch (item.key)
                {
                    // 冥思学习时间÷2.5
                    case nameof(ConfBattleSkillLearn.timeBas):
                    case nameof(ConfBattleSkillLearn.timeAdd):
                        item.value = (int)Math.Ceiling(item.value / 2.5);
                        break;
                    // 冥思球外溢数量×2.5
                    case nameof(ConfBattleSkillLearn.paraA):
                        item.value = (int)Math.Ceiling(item.value * 2.5);
                        break;
                    // 冥思球转化为[悟]\[魔]的时间÷2.5
                    case nameof(ConfBattleSkillLearn.turnMin):
                    case nameof(ConfBattleSkillLearn.turnMax):
                        item.value = (int)Math.Ceiling(item.value / 2.5);
                        break;
                    // 冥思球[悟]经验＋10×2.5%
                    case nameof(ConfBattleSkillLearn.expTimes1):
                    case nameof(ConfBattleSkillLearn.expTimes2):
                    case nameof(ConfBattleSkillLearn.expTimes3):
                    case nameof(ConfBattleSkillLearn.expTimes4):
                    case nameof(ConfBattleSkillLearn.expTimes5):
                    case nameof(ConfBattleSkillLearn.expTimes6):
                    case nameof(ConfBattleSkillLearn.expTimes7):
                    case nameof(ConfBattleSkillLearn.expTimes8):
                    case nameof(ConfBattleSkillLearn.expTimes9):
                    case nameof(ConfBattleSkillLearn.expTimes10):
                        item.value = (int)Math.Ceiling(item.value * 1.25);
                        break;
                    // 冥思球移动快慢降低10×2.5%
                    case nameof(ConfBattleSkillLearn.speedMin):
                    case nameof(ConfBattleSkillLearn.speedMax):
                        item.value = (int)Math.Ceiling(item.value * 0.75);
                        break;
                    default:
                        break;
                }
            }));
        }

        /// <summary>
        /// 物品拾取距离×2.5
        /// </summary>
        private void ModifyPropsPickDistance()
        {
            MelonLogger.Msg($"[{Settings.ModName}] Modify props pick distance");

            SceneType.battle.battleMap.playerUnitCtrl.dropDis.baseValue += 250;
        }
    }
}
